package me.firstapp.confg;

import java.io.IOException;
import java.sql.SQLException;
import java.util.Properties;

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.ehcache.EhCacheCacheManager;
import org.springframework.cache.ehcache.EhCacheManagerFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
import org.springframework.core.io.ClassPathResource;
import org.springframework.orm.hibernate5.HibernateTemplate;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.web.multipart.MultipartResolver;
import org.springframework.web.multipart.support.StandardServletMultipartResolver;

import com.alibaba.druid.pool.DruidDataSource;
import com.foxinmy.weixin4j.mp.WeixinProxy;
import com.weixin.message.common.MessageProcessor;

import me.firstapp.common.utils.SpringContextTool;
import me.firstapp.weixin.controller.interceptor.WeixinFilter;
import net.sf.ehcache.CacheManager;

@Configuration
@EnableCaching
@ImportResource("classpath:transaction.xml")
@ComponentScan(basePackages = { "me.firstapp.module", "me.firstapp.repository", "me.firstapp.service" })
public class RootConfig {

	@Bean
	public PropertiesFactoryBean configProperties() {
		PropertiesFactoryBean configProperties = new PropertiesFactoryBean();
		configProperties.setLocations(new ClassPathResource("jdbc.properties"),
				new ClassPathResource("config.properties"));
		return configProperties;
	}

	@Bean
	public MessageProcessor messageProcessor() {
		return new MessageProcessor();
	}

	// ==============================数据源配置==================================
	@Bean
	public DruidDataSource dataSource(PropertiesFactoryBean configProperties) {
		DruidDataSource druidDataSource = new DruidDataSource();
		try {
			Properties properties = configProperties.getObject();
			// 基本属性 url、user、password
			druidDataSource.setUrl(properties.getProperty("database.jdbcUrl"));
			druidDataSource.setUsername(properties.getProperty("database.user"));
			druidDataSource.setPassword(properties.getProperty("database.password"));
			// 配置初始化大小、最小、最大
			druidDataSource.setInitialSize(Integer.valueOf(properties.getProperty("database.initialSize")));
			druidDataSource.setMinIdle(Integer.valueOf(properties.getProperty("database.minIdle")));
			druidDataSource.setMaxActive(Integer.valueOf(properties.getProperty("database.maxActive")));
			// 配置获取连接等待超时的时间
			druidDataSource.setMaxWait(Integer.valueOf(properties.getProperty("database.maxWait")));
			// 配置一个连接在池中最小生存的时间，单位是毫秒
			druidDataSource.setMinEvictableIdleTimeMillis(
					Integer.valueOf(properties.getProperty("database.minEvictableIdleTimeMillis")));
			druidDataSource.setValidationQuery(properties.getProperty("database.validationQuery"));
			druidDataSource.setTestWhileIdle(Boolean.valueOf(properties.getProperty("database.testWhileIdle")));
			druidDataSource.setTestOnBorrow(Boolean.valueOf(properties.getProperty("database.testOnBorrow")));
			druidDataSource.setTestOnReturn(Boolean.valueOf(properties.getProperty("database.testOnReturn")));

			// 打开PSCache，并且指定每个连接上PSCache的大小
			druidDataSource.setPoolPreparedStatements(
					Boolean.valueOf(properties.getProperty("database.poolPreparedStatements")));
			druidDataSource.setMaxPoolPreparedStatementPerConnectionSize(
					Integer.valueOf(properties.getProperty("database.maxPoolPreparedStatementPerConnectionSize")));

			// 配置监控统计拦截的filters
			druidDataSource.setFilters("stat");
		} catch (IOException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return druidDataSource;
	}

	// ============================hibernate配置=====================================
	@Bean
	public LocalSessionFactoryBean sessionFactory(DruidDataSource dataSource) {
		LocalSessionFactoryBean sessionFactory = new LocalSessionFactoryBean();
		sessionFactory.setDataSource(dataSource);
		Properties properties = new Properties();
		properties.put("hibernate.dialect", "org.hibernate.dialect.MySQL5InnoDBDialect");
		properties.put("hibernate.show_sql", false);
		properties.put("hibernate.hbm2ddl.auto", "update");
		sessionFactory.setHibernateProperties(properties);
		sessionFactory.setPackagesToScan("me.firstapp.module", "me.firstapp.common");
		return sessionFactory;
	}

	@Bean
	public HibernateTemplate hibernateTemplate(LocalSessionFactoryBean sessionFactory) {
		HibernateTemplate hibernateTemplate = new HibernateTemplate();
		hibernateTemplate.setSessionFactory(sessionFactory.getObject());
		return hibernateTemplate;
	}

	// =================================事务配置==================================================
	@Bean
	public HibernateTransactionManager transactionManager(SessionFactory sessionFactory) {
		HibernateTransactionManager transactionManager = new HibernateTransactionManager();
		transactionManager.setSessionFactory(sessionFactory);
		return transactionManager;
	}

	@Bean
	public TransactionTemplate transactionTemplate(HibernateTransactionManager transactionManager) {
		TransactionTemplate transactionTemplate = new TransactionTemplate();
		transactionTemplate.setTransactionManager(transactionManager);
		return transactionTemplate;
	}

	@Bean
	public SpringContextTool springContextTool() {
		return new SpringContextTool();
	}

	// multipart请求
	@Bean
	public MultipartResolver multipartResolver() {
		return new StandardServletMultipartResolver();
	}

	@Bean
	public WeixinFilter weixinFilter() {
		return new WeixinFilter();
	}

	// ===============缓存================
	@Bean
	public EhCacheCacheManager cacheManager(CacheManager cm) {
		return new EhCacheCacheManager(cm);
	}

	@Bean
	public EhCacheManagerFactoryBean ehcache() {
		EhCacheManagerFactoryBean ehCacheFactoryBean = new EhCacheManagerFactoryBean();
		ehCacheFactoryBean.setConfigLocation(new ClassPathResource("ehcache.xml"));
		return ehCacheFactoryBean;
	}

	@Bean
	public WeixinProxy weixinProxy() {
		return new WeixinProxy();
	}
}
